#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import urllib
import hashlib
import jinja2
import os
import webapp2

import model

from functools import wraps
from google.appengine.api import users

from session import Session


class AttrDict(dict):
    def __getattr__(self, x):
        return dict.get(self, x, dict.__getattr__(self, x))

    def __setattr__(self, x):
        dict.__setitem__(self, x)


class RequestHandler(webapp2.RequestHandler):
    default_template = None
    require_user = False
    title_suffix = ""

    def __init__(self, *args, **kwargs):
        webapp2.RequestHandler.__init__(self, *args, **kwargs)
        for name in ("get","post","put","head","delete"):
            if hasattr(self, name):
                setattr(self, name, self._session_decorator(
                    getattr(self, name)))

    @property
    def session(self):
        return self.request.registry["session"]

    def add_message(self, msg):
        if "messages" in self.session:
            self.session["messages"].append(msg)
        else:
            self.session["messages"] = [msg]

    def _session_decorator(self, f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            session = Session.from_cookie(self.request)
            if self.require_user and not "user" in session:
                self.redirect("/")
                return
            self.request.registry["session"] = session
            old_message_num = len(session.get("messages", ()))
            r = f(*args, **kwargs)
            new_message_num = len(session.get("messages", ()))
            if old_message_num != new_message_num:
                # Make sure session's update flag is True
                session.changed = True
            session.write(self.response)
            return r
        return wrapper

    def render_template(self, template=None, **template_variables):
        template = jinja_environment.get_template( template or self.default_template )

        messages = self.session.get("messages", ())
        if messages:
            del self.session["messages"]

        if self.session.get("user", None):
            login_urls = (
                ("Logout", "Logout from this site", "logout", LoginPage.logout(self.request.url)),
                )
        else:
            login_urls = (
                ("Google login", "Login with google account", "google", LoginPage.login(self.request.url, "google")),
                )

        if not "title_suffix" in template_variables:
            template_variables["title_suffix"] = self.title_suffix
            
        self.response.out.write( template.render(
            logged="user" in self.session,
            session=self.session,
            messages=messages,
            login_urls=login_urls,
            **template_variables
            ))

    def redirect(self, url, *args, **kwargs):
        webapp2.RequestHandler.redirect(self, str(url), *args, **kwargs)
        

class MainPage(RequestHandler):
    default_template = 'index'

    def get(self):
        unanswered = model.get_questions_no_answered(20)
        self.render_template(unanswered=unanswered)


class TestPage(RequestHandler):
    default_template = 'test'

    def get(self):
        unanswered = model.get_questions_no_answered(20)
        self.render_template(unanswered=unanswered)
        

class NewQuestionPage(RequestHandler):
    default_template = 'ask'
    require_user = True

    def get(self):
        self.render_template( )

    def post(self):
        title = self.request.get("title")
        message = self.request.get("message")
        try:
            model.Question.save(
                self.session["user"]["id"],
                title,
                message
                )
            self.add_message("Question pusblished")
        except BaseException as e:
            self.add_message(e)
        self.redirect("/")


class QuestionPage(RequestHandler):
    default_template = "question"
    def get(self, qid, qtitle=None):
        question, answers = model.get_question_with_answers(qid)
        self.render_template(question=question, answers=answers)


class LoginPage(RequestHandler):

    @classmethod
    def login(cls, next_url, method):
        return "/login?%s" % urllib.urlencode({
            "next": next_url,
            "method": method
            })

    @classmethod
    def logout(cls, next_url):
        return "/login?%s" % urllib.urlencode({
            "next": next_url,
            "logout": "1"
            })

    def login_google(self):
        self.redirect(users.create_login_url(
            "/login?%s" % urllib.urlencode({
                "next": self.request.GET.get("next","/"),
                "handle": "google"
                })
            ))
        return True

    def logout_google(self):
        self.redirect(users.create_logout_url(
            "/login?%s" % urllib.urlencode({
                "next": self.request.GET.get("next","/"),
                "handle": "google"
                })
            ))
        return True

    def handle_google(self):
        user = users.get_current_user()
        if user:
            self.session["user"] = {
                "id":"google:%s" % user.user_id(),
                "name":user.nickname(),
                "avatar":gravatar(user.email(), 100, "%s/static/noavatar.png" % self.request.host_url),
                "method":"google"
                }
            self.add_message("Logged!")
        elif "user" in self.session and self.session["user"]["method"] == "google":
            del self.session["user"]
            self.add_message("Unlogged!")
    
    def get(self):
        handle = self.request.GET.get("handle", None)
        method = self.request.GET.get("method", None)
        logout = self.request.GET.get("logout", None)
        redirected = False
        if handle:
            method = "handle_%s" % handle
            if hasattr(self, method):
                redirected = getattr(self, method)()
        elif logout and "user" in self.session:
            method = "logout_%s" % self.session["user"]["method"]
            if hasattr(self, method):
                redirected = getattr(self, method)()
        elif method:
            method = "login_%s" % method
            if hasattr(self, method):
                redirected = getattr(self, method)()
        if not redirected:
            self.redirect(self.request.GET.get("next", "/"))

def gravatar(email, size, default):
    return "http://www.gravatar.com/avatar/%s?%s" % (
        hashlib.md5(email.lower()).hexdigest(),
        urllib.urlencode({'d':default, 's':str(size)})
        )

jinja_environment = jinja2.Environment(
    trim_blocks=True,
    loader=jinja2.FileSystemLoader(
        os.path.join(os.path.dirname(__file__), 'html')))

jinja_environment.globals["application"] = AttrDict(
    title = "quanda"
    )

application = webapp2.WSGIApplication((
    ('/questions/ask', NewQuestionPage),
    ('/questions/(.*)/(.*)', QuestionPage),
    ('/questions/(.*)/', QuestionPage),
    ('/questions/(.*)', QuestionPage),
    ('/login', LoginPage),
    ('/', MainPage),
    ), debug=True)
